package com.sdk.sdkdemo;

import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Environment;

import com.sdk.util.LogUtils;

import java.io.File;
import java.lang.reflect.Method;

import dalvik.system.PathClassLoader;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class HookMainLoader implements IXposedHookLoadPackage {
    private final String Tag  = "HookMainLoader";
    private final String mModulePackage = "com.sdk.sdkdemo";
    private final String mHookEntryClass = SdkXposed.class.getName();
    private final String mHookEntryMethod = "handleLoadPackage";

    @Override
    public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        if(loadPackageParam.packageName.equals("com.cleanmaster.mguard") || loadPackageParam.packageName.equals("com.cmcm.uangme")
                || loadPackageParam.packageName.equals("com.publisher.sample") || loadPackageParam.packageName.equals("com.tencent.bugly.demo")
                || loadPackageParam.packageName.equals("com.my.targetDemoApp") || loadPackageParam.packageName.equals("com.ksmobile.cb")
                || loadPackageParam.packageName.equals("com.sdk.flurrysdkdemo") || loadPackageParam.packageName.equals("com.turbochilli.rollingsky")
                || loadPackageParam.packageName.equals("")) {
            XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    Context context = (Context)param.args[0];
                    loadPackageParam.classLoader = context.getClassLoader();
                    invokeHandleHookMethod(context, mModulePackage, mHookEntryClass, mHookEntryMethod, loadPackageParam);
                }
            });
        }
    }

    boolean mIsLoader;
    private void invokeHandleHookMethod(Context context, String modulePackageName, String handleHookClass, String handleHookMethod, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        if(mIsLoader){
            return;
        }
        mIsLoader = true;
        File apkFile=findApkFile(context,modulePackageName);
        //Log.d(Tag, "path: " +  apkFile.getAbsolutePath());
        if (apkFile==null){
            throw new RuntimeException("寻找模块apk失败");
        }
        //加载指定的hook逻辑处理类，并调用它的handleHook方法
        PathClassLoader pathClassLoader = new PathClassLoader(apkFile.getAbsolutePath(), ClassLoader.getSystemClassLoader());
        Class<?> cls = Class.forName(handleHookClass, true, pathClassLoader);
        Object instance = cls.newInstance();
        Method method = cls.getDeclaredMethod(handleHookMethod, XC_LoadPackage.LoadPackageParam.class);
        method.invoke(instance, loadPackageParam);
    }

    private File findApkFile(Context context,String modulePackageName){
        if (context==null){
            //Log.d(Tag, "This is not possible");
            return null;
        }
        try {
            Context moudleContext = context.createPackageContext(modulePackageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
            String apkPath=moudleContext.getPackageCodePath();
            return new File(apkPath);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}
